package com.quectel.cms.controller.partybuildingmeeting;


import com.quectel.business.common.partybuilding.PartyPersonBusiness;
import com.quectel.business.common.partybuilding.PartyPersonMsgBusiness;
import com.quectel.business.common.util.sys.SysCodeUtils;
import com.quectel.cms.controller.BaseController;
import com.quectel.constant.PushConstants;
import com.quectel.constant.core.mobileuser.MobileUserMsgConstants;
import com.quectel.constant.core.partybuilding.PartyBuildingConstants;
import com.quectel.constant.core.partybuilding.PartyBuildingMeetingConstants;
import com.quectel.constant.global.SystemConstants;
import com.quectel.util.aspect.log.annotation.Log;
import com.quectel.constant.global.annotation.RequirePermissions;
import com.quectel.constant.sys.SysCodeKeyConstants;
import com.quectel.core.module.mobileuser.dto.MobileUserDto;
import com.quectel.core.module.mobileuser.service.MobileUserService;
import com.quectel.core.module.partybuilding.dto.PartyPersonDto;
import com.quectel.core.module.partybuilding.service.PartyPersonService;
import com.quectel.core.module.partybuildingmeeting.dto.PartyBuildingMeetingDto;
import com.quectel.core.module.partybuildingmeeting.dto.PartyBuildingMeetingPersonBindingDto;
import com.quectel.core.module.partybuildingmeeting.service.PartyBuildingMeetingPersonBindingService;
import com.quectel.core.module.partybuildingmeeting.service.PartyBuildingMeetingService;
import com.quectel.util.common.*;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author bob
 * @email bob.yu@quectel.com
 * @date 2023/05/24 11:38
 */
@RestController
@RequestMapping("partyBuildingMeeting")
@Tag(name = "PartyBuildingMeetingController", description = "党建三会一课-主题党日-组织生活会管理相关api")
public class PartyBuildingMeetingController extends BaseController {

    @DubboReference
    private PartyBuildingMeetingService partyBuildingMeetingService;
    @DubboReference
    private PartyBuildingMeetingPersonBindingService meetingPersonBindingService;
    @DubboReference
    private PartyPersonService partyPersonService;
    @DubboReference
    private MobileUserService mobileUserService;

    @Autowired
    private PartyPersonBusiness partyPersonBusiness;
    @Autowired
    private PartyPersonMsgBusiness partyPersonMsgBusiness;

    /**
     * 提前结束
     * @param id
     * @return
     */
    @PostMapping("finishEarly")
    @Operation(summary = "提前结束")
    public Response<Object> finishEarly(@RequestBody Long id) {

        Map<String, Object> params = new HashMap<>();
        super.fillAuthorityData(params);

        params.remove(SystemConstants.ENTITY_ID_FLAG);
        params.put(SystemConstants.ENTITY_ID_FLAG, String.valueOf(id));

        if (partyBuildingMeetingService.queryTotal(params) <= 0) {
            return Response.error(SystemConstants.ILLEGAL_MSG);
        }

        PartyBuildingMeetingDto updately = new PartyBuildingMeetingDto();
        updately.setId(id);
        updately.setEndTime(new Date());
        partyBuildingMeetingService.updateById(updately);
        return Response.ok();
    }

    /**
     * 编辑会议纪要
     *
     * @param partyBuildingMeetingDto
     * @return
     */
    @PostMapping("updateSummary")
    @Operation(summary = "编辑会议纪要")
    public Response<Object> saveSummary(@RequestBody @Validated PartyBuildingMeetingDto partyBuildingMeetingDto) {
        partyBuildingMeetingService.updateById(partyBuildingMeetingDto);
        return Response.ok();
    }

    /**
     * 查看会议纪要
     *
     * @param id
     * @return
     */
    @GetMapping("summaryInfo/{id}")
    @Operation(summary = "查看会议纪要")
    public Response<PartyBuildingMeetingDto> summaryInfo(@PathVariable("id") Long id) {
        Map<String, Object> params = new HashMap<>();
        super.fillAuthorityData(params);
        params.put(SystemConstants.ENTITY_ID_FLAG, String.valueOf(id));
        if (partyBuildingMeetingService.queryTotal(params) <= 0) {
            return Response.error(SystemConstants.ILLEGAL_MSG);
        }
        PartyBuildingMeetingDto partyBuildingMeetingDto = partyBuildingMeetingService.selectById(id);
        return Response.<PartyBuildingMeetingDto>ok().wrap(partyBuildingMeetingDto);
    }

    /**
     * 列表
     */
    @GetMapping("exportExcel")
    @RequirePermissions(values = "car:exportExcel")
    @Operation(summary = "导出党建活动记录")
    @Log(express = "导出党建活动记录")
    public void exportExcel(@RequestParam Map<String, Object> params, HttpServletResponse hresp) {
        Request request = Request.configParamsNotPage(params);

        String title = SysCodeUtils.easyToGetName(SysCodeKeyConstants.PARTY_BUILDING_MEETING, request.getByte("category") + "");

        super.fillAuthorityData(params);

        List<PartyBuildingMeetingDto> result = new ArrayList<>();
        int pageNo = 0;
        params.put("limit", 1000);
        while (true) {
            params.put("offset", pageNo++ * 1000);
            List<PartyBuildingMeetingDto> list = partyBuildingMeetingService.queryList(request.getParams());
            if (org.apache.commons.collections4.CollectionUtils.isEmpty(list)) {
                break;
            }
            result.addAll(list);
            if (list.size() < 1000) {
                break;
            }
        }
        String[] headers = new String[]{"所属党组织", "会议主题", "会议类型", "会议地点", "主持人", "会议开始时间", "会议结束时间", "参会人数", "心得数量", "创建时间"};
        List<String[]> dataList = new ArrayList<>();
        for (PartyBuildingMeetingDto data : result) {
            String[] item = new String[headers.length];
            item[0] = data.getPartyName();
            item[1] = data.getSubject();
            item[2] = partyPersonBusiness.getCategoryAndType(data)[1];
            item[3] = data.getAddress();
            item[4] = data.getHost();
            item[5] = DateUtils.format(data.getStartTime(), DateUtils.FormatType.COMMON);
            item[6] = DateUtils.format(data.getEndTime(), DateUtils.FormatType.COMMON);
            item[7] = data.getTotalJoinCount() + "/" + data.getTotalPersonCount();
            item[8] = data.getMeetingExperienceCount() + "";
            item[9] = DateUtils.format(data.getCreateTime(), DateUtils.FormatType.COMMON);

            dataList.add(item);
        }
        POIUtils.exportExcel(hresp, title, headers, dataList, title);

    }


    @PostMapping("release")
    @RequirePermissions(values = "partyBuildingMeeting:cancel")
    @Operation(summary = "发布操作")
    public Response<Object> release(@RequestBody Long id) {

        Map<String, Object> params = new HashMap<>();
        super.fillAuthorityData(params);
        params.put(SystemConstants.ENTITY_ID_FLAG, String.valueOf(id));
        if (partyBuildingMeetingService.queryTotal(params) <= 0) {
            return Response.error(SystemConstants.ILLEGAL_MSG);
        }

        PartyBuildingMeetingDto updately = new PartyBuildingMeetingDto();
        updately.setId(id);
        updately.setStatus(SystemConstants.YES);
        updately.setEditTime(new Date());
        partyBuildingMeetingService.updateById(updately);

        PartyBuildingMeetingDto dbValue = partyBuildingMeetingService.selectById(id);
        if (SystemConstants.YES.equals(dbValue.getStatus())
                && PartyBuildingMeetingConstants.RemindType.INSTANT_REMINDER.getType().equals(dbValue.getRemindType()) ) {

            List<PartyPersonDto> partyPersonList = getBindPersonList(dbValue);
            List<MobileUserDto> sendUserList = getSendUserList(partyPersonList);

            Byte category = dbValue.getCategory();
            MobileUserMsgConstants.SourceType meetingSourceType = CATEGORY_SOURCE_MAP.get(category);

            if (CollectionUtils.isNotEmpty(sendUserList) && meetingSourceType != null) {
                partyPersonMsgBusiness.pushMsg(
                        dbValue.getTenantId(),
                        sendUserList,
                        meetingSourceType,
                        dbValue.getId(),
                        String.format(PartyBuildingConstants.PUSH_MSG_MEETING_TITLE, meetingSourceType.getDefaultTitle()),
                        String.format(PartyBuildingConstants.PUSH_MSG_TEMPLATE,
                                dbValue.getSubject(),
                                DateUtils.format(dbValue.getStartTime(), DateUtils.FormatType.COMMON),
                                DateUtils.format(dbValue.getEndTime(), DateUtils.FormatType.COMMON)
                        ),
                        true,
                        new PushConstants.PushType[]{PushConstants.PushType.WECHAT_OFFICIAL}
                );
            }
        }

        return Response.ok();
    }

    @PostMapping("cancel")
    @RequirePermissions(values = "partyBuildingMeeting:cancel")
    @Operation(summary = "取消操作")
    public Response<Object> cancel(@RequestBody Long id) {

        Map<String, Object> params = new HashMap<>();
        super.fillAuthorityData(params);
        params.put(SystemConstants.ENTITY_ID_FLAG, String.valueOf(id));
        if (partyBuildingMeetingService.queryTotal(params) <= 0) {
            return Response.error(SystemConstants.ILLEGAL_MSG);
        }

        PartyBuildingMeetingDto updately = new PartyBuildingMeetingDto();
        updately.setId(id);
        updately.setStatus(PartyBuildingMeetingConstants.MeetingStatus.CANCEL.getStatus());
        updately.setEditTime(new Date());
        partyBuildingMeetingService.updateById(updately);

        return Response.ok();
    }

    /**
     * 分页查询
     *
     * @param pageNo
     * @param pageSize
     * @return
     */
    @GetMapping("list")
    @RequirePermissions(values = "partyBuildingMeeting:list")
    @Operation(summary = "分页获取党建三会一课-主题党日-组织生活会管理列表")
    public Response<Page<PartyBuildingMeetingDto>> list(
            @Parameter(description = "从1开始的页码数") @RequestParam Integer pageNo,
            @Parameter(description = "每页多少条") @RequestParam Integer pageSize
    ) {
        //查询列表数据
        Request request = Request.configParams(Request.parseParams(httpServletRequest));

        super.fillAuthorityData(request.getParams());
        int total = partyBuildingMeetingService.queryTotal(request.getParams());

        List<PartyBuildingMeetingDto> list = null;
        if (total > 0) {
            list = partyBuildingMeetingService.queryList(request.getParams());
        } else {
            list = new ArrayList<>();
        }

        Page<PartyBuildingMeetingDto> page = new Page<>(request.getPageNo(), request.getPageSize(), total, list);
        return Response.<Page<PartyBuildingMeetingDto>>ok().wrap(page);
    }

    /**
     * 编辑查询反显
     *
     * @param id
     * @return
     */
    @GetMapping("infoForEdit/{id}")
    @RequirePermissions(values = "partyBuildingMeeting:edit")
    @Operation(summary = "在编辑时根据id查询党建三会一课-主题党日-组织生活会管理详情")
    public Response<PartyBuildingMeetingDto> infoForEdit(@PathVariable("id") Long id) {

        Map<String, Object> params = new HashMap<>();
        super.fillAuthorityData(params);
        params.put(SystemConstants.ENTITY_ID_FLAG, String.valueOf(id));
        if (partyBuildingMeetingService.queryTotal(params) <= 0) {
            return Response.error(SystemConstants.ILLEGAL_MSG);
        }

        PartyBuildingMeetingDto partyBuildingMeetingDto = partyBuildingMeetingService.selectById(id);

        List<PartyPersonDto> partyPersonDtoList = new ArrayList<>();
        List<PartyBuildingMeetingPersonBindingDto> bindingDtos = meetingPersonBindingService.selectList(id);
        if (CollectionUtils.isNotEmpty(bindingDtos)) {
            for (PartyBuildingMeetingPersonBindingDto bindingDto : bindingDtos) {
                PartyPersonDto personDto = partyPersonService.selectCacheById(bindingDto.getPartyPersonId());
                if (personDto != null) {
                    partyPersonDtoList.add(personDto);
                }
            }
        }
        partyBuildingMeetingDto.setPartyPersonList(partyPersonDtoList);

        return Response.<PartyBuildingMeetingDto>ok().wrap(partyBuildingMeetingDto);
    }

    /**
     * 详情
     *
     * @param id
     * @return
     */
    @GetMapping("info/{id}")
    @RequirePermissions(values = "partyBuildingMeeting:info")
    @Operation(summary = "根据id查询党建三会一课-主题党日-组织生活会管理的详情")
    public Response<PartyBuildingMeetingDto> info(@PathVariable("id") Long id) {

        Map<String, Object> params = new HashMap<>();
        super.fillAuthorityData(params);
        params.put(SystemConstants.ENTITY_ID_FLAG, String.valueOf(id));
        if (partyBuildingMeetingService.queryTotal(params) <= 0) {
            return Response.error(SystemConstants.ILLEGAL_MSG);
        }

        PartyBuildingMeetingDto partyBuildingMeetingDto = partyBuildingMeetingService.selectById(id);

        return Response.<PartyBuildingMeetingDto>ok().wrap(partyBuildingMeetingDto);
    }

    /**
     * 保存
     *
     * @param partyBuildingMeetingDto
     * @return
     */
    @PostMapping("save")
    @RequirePermissions(values = "partyBuildingMeeting:edit")
    @Operation(summary = "新增党建三会一课-主题党日-组织生活会管理")
    public Response<Object> save(@RequestBody @Validated PartyBuildingMeetingDto partyBuildingMeetingDto) {
        Map<String, Object> params = new HashMap<>();
        //填充基础数据
        fillSaveCommonData(partyBuildingMeetingDto);

        Long partyBuildingMeetingId = null;

        // 不推送或者即时推送
        if (PartyBuildingMeetingConstants.RemindType.INSTANT_REMINDER.getType().equals(partyBuildingMeetingDto.getRemindType())
            || PartyBuildingMeetingConstants.RemindType.NO_NEED.getType().equals(partyBuildingMeetingDto.getRemindType())
        ){
            partyBuildingMeetingDto.setIsPush(SystemConstants.YES);
        }else {
            partyBuildingMeetingDto.setIsPush(SystemConstants.NO);
        }


        if (CollectionUtils.isEmpty(partyBuildingMeetingDto.getPartyPersonList())){
            return Response.error("请选择参会人员");
        }
        partyBuildingMeetingId = partyBuildingMeetingService.saveOrUpdate(partyBuildingMeetingDto);

        if (SystemConstants.YES.equals(partyBuildingMeetingDto.getStatus())
            && PartyBuildingMeetingConstants.RemindType.INSTANT_REMINDER.getType().equals(partyBuildingMeetingDto.getRemindType()) ) {

            List<PartyPersonDto> partyPersonList = getBindPersonList(partyBuildingMeetingService.selectCacheById(partyBuildingMeetingId));
            List<MobileUserDto> sendUserList = getSendUserList(partyPersonList);

            Byte category = partyBuildingMeetingDto.getCategory();
            MobileUserMsgConstants.SourceType meetingSourceType = CATEGORY_SOURCE_MAP.get(category);

            if (CollectionUtils.isNotEmpty(sendUserList) && meetingSourceType != null) {
                PartyBuildingMeetingDto dbValue = partyBuildingMeetingService.selectCacheById(partyBuildingMeetingId);
                partyPersonMsgBusiness.pushMsg(
                        dbValue.getTenantId(),
                        sendUserList,
                        meetingSourceType,
                        partyBuildingMeetingId,
                        String.format(PartyBuildingConstants.PUSH_MSG_MEETING_TITLE, meetingSourceType.getDefaultTitle()),
                        String.format(PartyBuildingConstants.PUSH_MSG_TEMPLATE,
                                dbValue.getSubject(),
                                DateUtils.format(dbValue.getStartTime(), DateUtils.FormatType.COMMON),
                                DateUtils.format(dbValue.getEndTime(), DateUtils.FormatType.COMMON)
                        ),
                        true,
                        new PushConstants.PushType[]{PushConstants.PushType.WECHAT_OFFICIAL}
                );
            }
        }
        return Response.ok();
    }


    /**
     * 修改
     *
     * @param partyBuildingMeetingDto
     * @return
     */
    @PostMapping("update")
    @RequirePermissions(values = "partyBuildingMeeting:edit")
    @Operation(summary = "根据id修改党建三会一课-主题党日-组织生活会管理")
    public Response<Object> update(@RequestBody @Validated PartyBuildingMeetingDto partyBuildingMeetingDto) {

        Map<String, Object> params = new HashMap<>();
        super.fillAuthorityData(params);
        params.put(SystemConstants.ENTITY_ID_FLAG, String.valueOf(partyBuildingMeetingDto.getId()));
        if (partyBuildingMeetingService.queryTotal(params) <= 0) {
            return Response.error(SystemConstants.ILLEGAL_MSG);
        }
        //填充基础数据
        fillEditCommonData(partyBuildingMeetingDto);

        params.remove(SystemConstants.ENTITY_ID_FLAG);

        // 不推送或者即时推送
        if (PartyBuildingMeetingConstants.RemindType.INSTANT_REMINDER.getType().equals(partyBuildingMeetingDto.getRemindType())
                || PartyBuildingMeetingConstants.RemindType.NO_NEED.getType().equals(partyBuildingMeetingDto.getRemindType())
        ){
            partyBuildingMeetingDto.setIsPush(SystemConstants.YES);
        }else {
            partyBuildingMeetingDto.setIsPush(SystemConstants.NO);
        }

        if (CollectionUtils.isEmpty(partyBuildingMeetingDto.getPartyPersonList())){
            return Response.error("请选择参会人员");
        }
        partyBuildingMeetingService.saveOrUpdate(partyBuildingMeetingDto);
        return Response.ok();
    }

    /**
     * 批量删除
     *
     * @param ids
     * @return
     */
    @PostMapping("delete")
    @RequirePermissions(values = "partyBuildingMeeting:delete")
    @Operation(summary = "根据多条记录id批量删除党建三会一课-主题党日-组织生活会管理")
    public Response<Object> delete(@RequestBody Long[] ids) {

        Map<String, Object> params = new HashMap<>();
        super.fillAuthorityData(params);

        for (Long id : ids) {

            params.remove(SystemConstants.ENTITY_ID_FLAG);
            params.put(SystemConstants.ENTITY_ID_FLAG, String.valueOf(id));

            if (partyBuildingMeetingService.queryTotal(params) <= 0) {
                return Response.error(SystemConstants.ILLEGAL_MSG);
            }
        }

        partyBuildingMeetingService.deleteBatch(ids);

        return Response.ok();
    }

    // 构建分类和SourceType枚举常量的映射
    private static final Map<Byte, MobileUserMsgConstants.SourceType> CATEGORY_SOURCE_MAP = new HashMap<>();
    static {
        CATEGORY_SOURCE_MAP.put(PartyBuildingMeetingConstants.CategoryEnum.THREE_MEETINGS_ONE_LESSON.getCategory(), MobileUserMsgConstants.SourceType.THREE_MEETINGS_ONE_LESSON);
        CATEGORY_SOURCE_MAP.put(PartyBuildingMeetingConstants.CategoryEnum.THEME_PARTY_DAY.getCategory(), MobileUserMsgConstants.SourceType.THEME_PARTY_DAY);
        CATEGORY_SOURCE_MAP.put(PartyBuildingMeetingConstants.CategoryEnum.PARTY_LIFE_MEETING.getCategory(), MobileUserMsgConstants.SourceType.PARTY_LIFE_MEETING);
    }


    // 提取函数来获取发送用户列表
    private List<MobileUserDto> getSendUserList(List<PartyPersonDto> partyPersonList) {
        return partyPersonList.stream()
                .map(PartyPersonDto::getMobile)
                .map(mobileUserService::selectByMobile)
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
    }

    /**
     * 获取绑定的人员列表
     * @param meetingDto
     * @return
     */
    private List<PartyPersonDto> getBindPersonList(PartyBuildingMeetingDto meetingDto){
        List<PartyPersonDto> partyPersonDtoList = new ArrayList<>();
        List<PartyBuildingMeetingPersonBindingDto> bindList
                = meetingPersonBindingService.selectList(meetingDto.getId());
        if (CollectionUtils.isEmpty(bindList)){
            return partyPersonDtoList;
        }

        for (PartyBuildingMeetingPersonBindingDto bindingDto : bindList) {
            PartyPersonDto partyPersonDto = partyPersonService.selectCacheById(bindingDto.getPartyPersonId());
            if (partyPersonDto!=null){
                partyPersonDtoList.add(partyPersonDto);
            }
        }

        return partyPersonDtoList;

    }
}
